package top.lishuoboy.cloud.consumer.order80.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import top.lishuoboy.cloud.api.common.entry.CommonResult;
import top.lishuoboy.cloud.api.common.entry.Payment;
import top.lishuoboy.cloud.consumer.order80.service.PaymentFeignService;
import top.lishuoboy.dependency.base.json.HuJsonUtil;

import java.util.List;


@Slf4j
@RestController
@DefaultProperties(defaultFallback = "defaultFallbackMethod")   // 全局服务降级默认方法
public class OrderController {
    //public static final String PAYMENT_URL = "http://localhost:8001";
    public static final String PAYMENT_URL = "http://cloud-payment-service"; // Eureka服务 负载均衡
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    DiscoveryClient discoveryClient;
    @Autowired
    private PaymentFeignService paymentFeignService;

    /** http://localhost:8001/consumer/payment/create?serial=105 */
    @PostMapping("consumer/payment/create")
    public CommonResult<Payment> create(Payment payment) {
        return restTemplate.postForObject(PAYMENT_URL + "/provider/payment/create", payment, CommonResult.class);
    }

    /** http://localhost:8001/consumer/payment/get/1 */
    @GetMapping("consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
        return restTemplate.getForObject(PAYMENT_URL + "/provider/payment/get/" + id, CommonResult.class);
    }

    /** http://localhost:8001/consumer/payment/get/feign/1 */
    @GetMapping("consumer/payment/get/feign/{id}")
    public CommonResult<Payment> getPaymentFeign(@PathVariable("id") Long id) {
        return paymentFeignService.getPaymentById(id);
    }

    /** http://localhost:8001/consumer/payment/hystrix/ok */
    @HystrixCommand  // 不指定fallback方法，则使用全局默认方法
    @GetMapping("consumer/payment/hystrix/ok")
    public String paymentInfoOK() {
        // 造异常，不启动7001 Eureka（80调用过则有缓存，需重启80） 或 8001 payment
        return paymentFeignService.paymentInfoOK();
    }

    /** http://localhost:8001/consumer/payment/hystrix/timeout */
    @GetMapping("consumer/payment/hystrix/timeout")
    // fallbackMethod 指定善后方法名,超时或异常调用方法 paymentInfo_TimeOutHandler()
    @HystrixCommand(
        fallbackMethod = "paymentInfo_TimeOutHandler",
        commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
        })
    public String paymentInfoTimeOut() {
        return paymentFeignService.paymentInfoTimeOut();
    }

    // 用来善后的方法
    private String paymentInfo_TimeOutHandler() {
        return "线程:  " + Thread.currentThread().getName() + "  80 系统繁忙或者运行报错，请稍后再试";
    }

    // 全局默认fallback方法
    public String defaultFallbackMethod() {
        return "默认全局异常处理方法,80：请稍后再试，/(ㄒoㄒ)/~~";
    }

    /**
     * 服务发现
     * http://localhost:8001/consumer/payment/discovery
     */
    @GetMapping("consumer/payment/discovery")
    private void discoveryClient() {
        List<String> serviceList = discoveryClient.getServices();
        log.warn("serviceList=={}", serviceList);  // serviceList==[cloud-payment-service, cloud-order-service]

        List<ServiceInstance> serviceInstances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance service : serviceInstances) {
            log.warn(service.getServiceId() + "\t" + service.getHost() + "\t" + service.getPort() + "\t" + service.getUri());  // CLOUD-PAYMENT-SERVICE	lishuoboy-PC	8001	http://lishuoboy-PC:8001
            log.warn("service=={}", HuJsonUtil.toJsonPrettyStr(service));
            /**
             * 一个的
             * service=={
             *   "scheme" : "http",
             *   "host" : "lishuoboy-PC",
             *   "port" : 8001,
             *   "metadata" : {
             *     "management.port" : "8001"
             *   },
             *   "secure" : false,
             *   "serviceId" : "CLOUD-PAYMENT-SERVICE",
             *   "uri" : "http://lishuoboy-PC:8001",
             *   "instanceId" : "lishuoboy-PC:cloud-payment-service:8001",
             *   "instanceInfo" : {
             *     "instanceId" : "lishuoboy-PC:cloud-payment-service:8001",
             *     "app" : "CLOUD-PAYMENT-SERVICE",
             *     "appGroupName" : null,
             *     "ipAddr" : "169.254.51.222",
             *     "sid" : "na",
             *     "homePageUrl" : "http://lishuoboy-PC:8001/",
             *     "statusPageUrl" : "http://lishuoboy-PC:8001/actuator/info",
             *     "healthCheckUrl" : "http://lishuoboy-PC:8001/actuator/health",
             *     "secureHealthCheckUrl" : null,
             *     "vipAddress" : "cloud-payment-service",
             *     "secureVipAddress" : "cloud-payment-service",
             *     "countryId" : 1,
             *     "dataCenterInfo" : {
             *       "@class" : "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
             *       "name" : "MyOwn"
             *     },
             *     "hostName" : "lishuoboy-PC",
             *     "status" : "UP",
             *     "overriddenStatus" : "UNKNOWN",
             *     "leaseInfo" : {
             *       "renewalIntervalInSecs" : 30,
             *       "durationInSecs" : 90,
             *       "registrationTimestamp" : 1648667583393,
             *       "lastRenewalTimestamp" : 1648668604322,
             *       "evictionTimestamp" : 0,
             *       "serviceUpTimestamp" : 1648667583393
             *     },
             *     "isCoordinatingDiscoveryServer" : false,
             *     "metadata" : {
             *       "management.port" : "8001"
             *     },
             *     "lastUpdatedTimestamp" : 1648667583393,
             *     "lastDirtyTimestamp" : 1648667583379,
             *     "actionType" : "ADDED",
             *     "asgName" : null
             *   }
             * }
             */
        }
    }

    // ====================> zipkin+sleuth
    @GetMapping("/consumer/payment/zipkin")
    public String paymentZipkin() {
        String result = restTemplate.getForObject(PAYMENT_URL + "/provider/payment/zipkin/", String.class);
        return result;
    }
}